<template>
	<view class="form bgf">
		
		<template v-for="item,index in options" :key="index">
			<slot :name="item.key" v-if="$slots[item.key]" ></slot>
			<view class="" v-else>
				<formItemVue :title="item.name" :required="item.required" :flex="!['idcard','images'].includes(item.type)" :tips="item.tips">
					<input v-if="['text','number'].includes(item.type)"  
					:type="item.type" class="input" 
					:placeholder="item.placeholder || `请输入${item.name}` " 
					v-model="model[item.key]"
					:disabled="disabled"
					 />
					 <imgSelect v-model="model[item.key]" v-if="item.type == 'images'" :max="item.max || 9" :disabled="disabled" />
					 <areaSelect :disabled="disabled" v-model="model[item.key]" v-if="item.type == 'address'" :regeo="Boolean(item.regeo)" :placeholder="item.placeholder || `请选择${item.name}`"  />
					 <radioGroup :disabled="disabled" v-model="model[item.key]" v-if="item.type == 'radio'" :options="item.options"   />
					 <checkboxGroup :disabled="disabled" v-model="model[item.key]" v-if="item.type == 'checkbox'" :options="item.options" />
					 <idcard :disabled="disabled" v-if="item.type == 'idcard'" v-model="model[item.key]" />
					 <selectVue :disabled="disabled" v-model="model[item.key]" v-if="item.type == 'select'" :options="item.options"
					  :rangeKey="item.rangeKey || 'name'"
					  :valueKey="item.valueKey || 'id'"
					  />
					  <timSelect :disabled="disabled" v-model="model[item.key]" v-if="item.type == 'time'"/>
				</formItemVue>
			</view>
		</template>
	</view>
	
	
</template>

<script setup lang="ts">
import timSelect from './timeSelect.vue'
import selectVue from "./select.vue"
import idcard from "./idcard.vue"
import checkboxGroup from "./checkbox.vue"
import radioGroup from "./radioGroup.vue"
import areaSelect from	"./areaSelect.vue"
import imgSelect from "./imgSelect.vue"
import formItemVue from "./formItem.vue"
import { showToast, useVmodel } from "@/lib/ts/util"
import { WritableComputedRef } from "vue"
import { formItem } from "./types"
	
	
	let props =  defineProps({
		options:{
			type:Array<formItem>,
			default:[]
		},
		modelValue:{
			type:Object,
			default:{}
		},
		disabled:{
			type:Boolean,
			default:false
		}
	})
	
	const emit = defineEmits(['update:modelValue'])
	let model:WritableComputedRef<any>  //双向绑定的对象
	let row:object  //首次创建后的数据模板，用于清空数据时使用
	
	(()=>{
		let obj = {}
		props.options.forEach(item=>{
			let val:string | Array<any> = ''
			switch(item.type){
				case 'text': 
				case 'radio':
				case 'number':
				case 'address': 
				case 'select': 
				case 'time':
				break;
				case 'checkbox':
				case 'idcard':
				case 'images': val = []
				break;
				default: throw '不支持的数据类型：'+item.type
			}
			obj[item.key] = item.default || val
		})
		row = obj
		emit('update:modelValue',obj)
		model =  useVmodel(props,'modelValue',emit)
	})()
	
	
	const checkRules = ()=>{
		let flag = false
		let count = 0
		loop: for(let k in model.value){
			//不进行检测的类型
			let checkTypeBlackList = ['address']
			//获取每个字段的验证规则
			let target = props.options.find(item=>k == item.key)
			
			//跳过不需要验证的类型
			if(checkTypeBlackList.includes(target.type)) continue
			let rules = target.rules || []
			//验证
			for(let i=0;i<rules.length;i++){
				let res = rules[i](model.value[k])
				res = typeof res == 'boolean'?{msg:`${target.name}不符合规则`,flag:res}:{msg:target.name+res.msg,flag:res.flag}
				if(!res.flag){
					showToast(res.msg)
					break loop
				}
			}
			count++
			if(count == props.options.length) flag = true
		}
		return flag
	}
	
	
	const submit = (callback:(res:{code:number,row:object})=>any,toString=true)=>{
		let row = JSON.parse(JSON.stringify(model.value))
		if(toString){  //将数组转字符串
			for(let k in row){
				if(row[k] instanceof Array) row[k] = row[k].join(',')
			}
		}
		callback({
			code:checkRules()?1:0,
			row,
		})
	}
	
	const clear = ()=>{
		model.value = {...row}
	}
	
	const setValue = (data:Object)=>{
		props.options.forEach(item=>{
			if(data[item.key]){
				switch (item.type){
					case 'images':
					case 'checkbox':
						model.value[item.key] = data[item.key].split(',')
						break;
					default:
						model.value[item.key] = data[item.key]
						break;
				}
			}
		})
	}
	
	
	defineExpose({
		submit,
		clear,
		setValue
	})
	
	
	
	
</script>

<style scoped lang="scss">
	.input{
		text-align: right;
	}
	.form{
		width: 100%;
		padding: 0 20rpx;
		border-radius: 10rpx;
	}
	
</style>